package cn.backpackerxl.test;

import java.lang.reflect.*;

interface Ref<T> {

    T update(T e, String name);
}


class RefImpl<T> implements Ref<T> {
    @Override
    public T update(T t, String name) {
        try {
            Field filed = t.getClass().getDeclaredField(name);
            filed.setAccessible(true);
            filed.set(t, "dk");
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        return t;
    }
}

interface User extends Ref<Ig> {
    void name(String name);
}

class Ig {
    private String name;
    private String passwd;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPasswd() {
        return passwd;
    }

    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }

    public Ig(String name, String passwd) {
        this.name = name;
        this.passwd = passwd;
    }

    @Override
    public String toString() {
        return "Ig{" + "name='" + name + '\'' + ", passwd='" + passwd + '\'' + '}';
    }
}

class UserImpl extends RefImpl<Ig> implements User {
    private final static String prefix = "Hello ";

    @Override
    public void name(String name) {
        System.out.println(prefix + name);
    }
}


interface UserS {
    void hi();
}

class UserProxy implements InvocationHandler {

    private final Object obj;
    private final Class<?> clazzI;

    public UserProxy(Class<?> clazz) {
        this.obj = new RefImpl<>();
        if (!clazz.isInterface()) {
            throw new IllegalArgumentException(clazz.getName() + "is not a interface");
        }
        this.clazzI = clazz;
    }

    public UserProxy(Class<?> clazz, Object obj) {
        this.obj = obj;
        if (!clazz.isInterface()) {
            throw new IllegalArgumentException(clazz.getName() + "is not a interface");
        }
        this.clazzI = clazz;
    }

    public Object init() {
        return Proxy.newProxyInstance(this.obj.getClass().getClassLoader(), new Class[]{Ref.class, this.clazzI}, this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return method.invoke(this.obj, args);
    }
}

class UserSImpl implements UserS {
    private final User user = (User) new UserProxy(User.class, new UserImpl()).init();

    @Override
    public void hi() {
        user.name("dk");
        System.out.println(user.update(new Ig("jj", "122"), "passwd"));
    }
}


public class Exec {
    public static void main(String[] args) {

        UserS userS = new UserSImpl();

        userS.hi();

    }

}
